package com.googlecode.cardamomo.dbreveng.app;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;

import com.googlecode.cardamomo.dbreveng.DBMetaDataLoader;
import com.googlecode.cardamomo.ermodel.Schema;
import com.googlecode.cardamomo.ermodel.Table;
import com.googlecode.cardamomo.jaxb.NSPrefixMapper;

/**
 * Class DBRevEng is a main Java program that has the purpose to generate a XDM
 * file based on a table definition on a database
 * 
 * @author jtorne
 * 
 */
public class DBRevEng {

	private static ResourceBundle rb = null;
	private static Logger log = Logger.getLogger("dbreveng");
	private static String fileExtension = ".xdm";

	public Connection getConnection(String dbName, String url) {
		Connection con = null;

		String driverManager = rb.getString("jdbc.driverManager");
		String jdbcURL = rb.getString("jdbc.url");
		if (url != null)
			jdbcURL = url;
		String user = rb.getString("jdbc.user");
		String pwd = rb.getString("jdbc.passwd");
		// if (dbName != null)
		// jdbcURL += "/" + dbName;

		log.info("Loading driver " + driverManager + " for [" + jdbcURL + "]");
		try {
			Class.forName(driverManager);
			con = DriverManager.getConnection(jdbcURL, user, pwd);
		} catch (SQLException e) {
			log.log(Level.SEVERE, e.getLocalizedMessage());
			System.exit(1);
		} catch (ClassNotFoundException e) {
			log.log(Level.SEVERE, e.getLocalizedMessage());
			System.exit(1);
		}

		return con;
	}

	public DBRevEng() {

	}

	private ResourceBundle getProperties(String propfile) {
		InputStream is = null;
		try {
			is = new FileInputStream(propfile + ".properties");
		} catch (FileNotFoundException e) {
			is = ClassLoader
					.getSystemResourceAsStream(propfile + ".properties");
		}
		if (is != null) {
			PropertyResourceBundle ps = null;
			try {
				ps = new PropertyResourceBundle(is);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return ps;
		}
		return null;
	}

	static void usage() {
		System.err
				.println("Usage: java -cp cardamomo.jar " +
				DBRevEng.class.getName() 
				+ " <options>");
		System.err.println("	options:");
		System.err.println("		-u	<URL-JDBC>");
		System.err.println("		-d	<destination directory>");
		System.err.println("		-t	<table-name>");
		System.err.println("		-S	<schema>");
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		String jdbcURL = null;
		String outputDir = ".";

		// Inputs
		// Configuration from database2code.properties
		// Additional parameters from args
		// - args[1] = TableName

		DBRevEng db2c = new DBRevEng();
		rb = db2c.getProperties("dbreveng");

		String table = null;
		String schemaName = null;
		int iarg = 0;
		while (iarg < args.length) {
			if (args[iarg].equals("-t")) {
				iarg++;
				table = args[iarg];
				int index = table.indexOf('.');
				if (index > 0) {
					schemaName = table.substring(0, index);
					table = table.substring(index + 1);
				}
			} else if (args[iarg].equals("-S")) {
				iarg++;
				schemaName = args[iarg];
			} else if (args[iarg].equals("-u")) {
				iarg++;
				jdbcURL = args[iarg];
				iarg++;
				continue;
			} else if (args[iarg].equals("-d")) {
				iarg++;
				outputDir = args[iarg] + "/";
				iarg++;
				continue;
			} else {
				log.severe("'"+args[iarg]+"' is not a valid option");
				usage();
				System.exit(1);
			}
			iarg++;
		}

		DBMetaDataLoader loader = new DBMetaDataLoader(db2c.getConnection(
				schemaName, jdbcURL));
		Schema sm = null;
		try {
			sm = loader.getSchemaInfo(schemaName, false);
			loader.loadTableInfo(sm, schemaName, table);
		} catch (SQLException e) {
			log.severe("Error processing table " + table + ": "
					+ e.getLocalizedMessage());
			e.printStackTrace();
		}
		if (sm != null) {

			for (Iterator<Table> it = sm.getTables().iterator(); it.hasNext();) {
				Table tm;
				tm = it.next();
				if (tm.getType().equals("VIEW")) {
					continue;
				}
				log.info("Processing " + tm.getName());
				try {
					JAXBContext jc = JAXBContext.newInstance(Table.class);
					String fileName = null;
					if (outputDir != null)
						fileName = outputDir + "/" + tm.getName();
					else
						fileName = tm.getName();
					String fExt = rb.getString("file.extension");
					if (fExt == null || fExt.length() == 0)
						fExt = fileExtension;
					fileName = fileName + fExt;

					FileOutputStream fos = null;
					if (outputDir != null)
						fos = new FileOutputStream(fileName);
					Marshaller m;
					m = jc.createMarshaller();
					m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
							Boolean.TRUE);
					try {
						m.setProperty(
								"com.sun.xml.internal.bind.namespacePrefixMapper",
								new NSPrefixMapper());
					} catch (PropertyException e) {
						// In case another JAXB implementation is used
					}
					m.marshal(tm, (fos != null) ? fos : System.out);
				} catch (JAXBException e) {
					e.printStackTrace();
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		System.exit(0);
	}

}
